﻿Function.RegisterNamespace("Test.System.IO");

[Fixture,Trait("Integration")]
Test.System.IO.FileStrategy=function(){
    var _fileSystemError="The method or file system does not appear to be implemented. Please implement System.IO.File.IFileStrategy and register the Function pointer with System.IO.File.Strategies.Add(type)";
    var _tmpFile=System.IO.Path.Combine(System.Environment.GetWorkingDirectory(),"FileStrategyIntegrationTests.tmp");

    [Fixture]
    function DeleteFile(){
        [Fact]
        function DeletesExistingFile(){
            var targetFile=_tmpFile;
            System.IO.File.SaveFile(targetFile,'');
            
            System.IO.File.DeleteFile(targetFile);
            var actual=System.IO.File.Exists(targetFile);
            
            Assert.False(actual);
        }
    }

    [Fixture]
    function Exists(){
        [Fact]
        function ReturnsTrueIfFileExists(){
            var targetFile=_tmpFile;
            System.IO.File.SaveFile(targetFile,'');
            
            var actual=System.IO.File.Exists(targetFile);
            System.IO.File.DeleteFile(targetFile);
            
            Assert.True(actual,String.Format("Test.System.IO.FileStrategy.Exists.ReturnsTrueIfFileExists: {0}",_fileSystemError));
        }

        [Fact]
        function ReturnsFalseIfFileDoesNotExist(){
            var actual=System.IO.File.Exists('');
            
            Assert.False(actual,String.Format("Test.System.IO.FileStrategy.Exists.ReturnsFalseIfFileDoesNotExist: {0}",_fileSystemError));
        }
    }
    
    [Fixture]
    function GetFile(){
        [Fact]
        function ReturnsNullIfFileNotFound(){            
            var actual=System.IO.File.GetFile('');
            
            Assert.Null(actual);
        }
        
        [Fact]
        function GetsContentsOfFile(){
            var expected="expected";
            var targetFile=_tmpFile;
            System.IO.File.SaveFile(targetFile,expected);
            
            var actual=System.IO.File.GetFile(targetFile);
            System.IO.File.DeleteFile(targetFile);
            
            Assert.Equal(expected,actual);        
        }

        [Fact]
        function GetsContentsOfEmptyFile(){
            var expected='';
            var targetFile=_tmpFile;
            System.IO.File.SaveFile(targetFile,expected);
            
            var actual=System.IO.File.GetFile(targetFile);
            System.IO.File.DeleteFile(targetFile);
            
            Assert.Equal(expected,actual);        
        }

        [Fact]
        function GetsFileWithControlCharacterInName(){
            var expected='expected';
            var targetFile=_tmpFile+"^ & ' @ { } [ ], $ = ! - # ( ) % . + ~ _ Test.tmp";
            System.IO.File.SaveFile(targetFile,expected);
            
            var actual=System.IO.File.GetFile(targetFile);
            System.IO.File.DeleteFile(targetFile);
            
            Assert.Equal(expected,actual);
        }

    }
    
    [Fixture]
    function SaveFile(){
        [Fact]
        function CreatesFileIfItDoesNotExist(){
            var targetFile=_tmpFile;
            System.IO.File.DeleteFile(targetFile);
            
            System.IO.File.SaveFile(targetFile,'');
            var actual=System.IO.File.Exists(targetFile);
            System.IO.File.DeleteFile(targetFile);
            
            Assert.True(actual);        
        }

        [Fact]
        function SetsFileContents(){
            var expected="expected";
            var targetFile=_tmpFile;
            
            System.IO.File.SaveFile(targetFile,expected);
            var actual=System.IO.File.GetFile(targetFile);
            System.IO.File.DeleteFile(targetFile);
           
            Assert.Equal(expected,actual);        
        }

        [Fact]
        function SetsMultiLineFileContents(){
            var expected=["abc","def","ghi","jkl","mno"].join(System.Environment.GetNewLine());
            var targetFile=_tmpFile;
            
            System.IO.File.SaveFile(targetFile,expected);
            var actual=System.IO.File.GetFile(targetFile);
            System.IO.File.DeleteFile(targetFile);
           
            Assert.Equal(expected,actual);        
        }

        [Fact]
        function WritesLargeFile(){
            var expected="abcdefghijklmnopqrstuvwxyz";
            for(var i=0;i<15;i++)expected+=expected;
            var targetFile=_tmpFile;

            System.IO.File.SaveFile(targetFile,expected);
            var actual=System.IO.File.GetFile(targetFile);
            System.IO.File.DeleteFile(targetFile);
           
            Assert.True(expected==actual); // Don't use Assert.Equal here. In case of mismatch, we don't want to flood stdout with 27,262,976+ characters
        }

        [Fact]
        function WritesSpecialCharactersToFile(){
            var expected="`~!@#$%^&*()_+-=|}{\\';\":?></.,";
            // TODO: BUG: Writing open square bracket breaks _attributeRegex
            // TODO: BUG: V8.Windows and SpiderMonkey.Windows cannot handle double-quote
            var targetFile=_tmpFile;

            System.IO.File.SaveFile(targetFile,expected);
            var actual=System.IO.File.GetFile(targetFile);
            System.IO.File.DeleteFile(targetFile);
           
            Assert.Equal(expected,actual);
        }

        [Fact]
        function WritesUnicodeCharactersToFile(){
            var expected="✌ ಠ_ರೃ 私は俳句を愛する"; 
            // TODO: BUG: SpiderMonkey.Windows and V8.Windows cannot handle unicode
            var targetFile=_tmpFile;

            System.IO.File.SaveFile(targetFile,expected);
            var actual=System.IO.File.GetFile(targetFile);
            System.IO.File.DeleteFile(targetFile);
           
            Assert.Equal(expected,actual);
        }
    }        
}